package com.iflytek.cosmo.ocr.service.impl;

import java.sql.Date;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;

import com.iflytek.cosmo.ocr.common.enums.ResultCodeEnum;
import com.iflytek.cosmo.ocr.model.domain.State;
import com.iflytek.cosmo.ocr.service.RedisService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

/**
 * @author <a href=mailto:ktyi@iflytek.com>伊开堂</a>
 * @date 2020/4/21 15:09
 */
@Service
public class RedisServiceImpl implements RedisService {
    private static final Logger logger = LoggerFactory.getLogger(RedisServiceImpl.class);

    private static final String RECOGNIZE_PAGE_COUNT_PATTERN = "recognize_count:%s:%s";

    @Value("${recognize.page.daily.limit:-1}")
    private int pageDailyLimit;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public int getRemainRecognizePageSize(String userId) {
        if (pageDailyLimit == -1) {
            return -1;
        }

        LocalDateTime now = LocalDateTime.now();

        // 构造key
        String date = now.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        String key = String.format(RECOGNIZE_PAGE_COUNT_PATTERN, date, userId);
        ValueOperations<String, Object> operations = redisTemplate.opsForValue();
        Object existValue = operations.get(key);
        if (existValue == null) {
            return pageDailyLimit;
        }

        if (existValue instanceof Integer) {
            return (Integer) existValue >= pageDailyLimit ? 0 : pageDailyLimit - (Integer) existValue;
        }
        else {
            try {
                return Integer.parseInt(String.valueOf(existValue));
            }
            catch (NumberFormatException e) {
                logger.warn("Redis已识别页数数据解析异常, key: {}, redisValue: {}", key, existValue, e);
                return pageDailyLimit;
            }
        }
    }

    @Override
    public State increamentRecognizePageCount(String userId, int increament) {
        LocalDateTime now = LocalDateTime.now();

        // 构造key
        String date = now.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        String key = String.format(RECOGNIZE_PAGE_COUNT_PATTERN, date, userId);
        ValueOperations<String, Object> operations = redisTemplate.opsForValue();
        Object existValue = operations.get(key);

        // 判断已识别页数
        int currentCount = 0;
        if (existValue != null) {
            if (existValue instanceof Integer) {
                currentCount = (Integer) existValue;
            }
            else {
                try {
                    currentCount = Integer.parseInt(String.valueOf(existValue));
                }
                catch (NumberFormatException e) {
                    logger.warn("Redis已识别页数数据解析异常, key: {}, redisValue: {}", key, existValue, e);
                }
            }
        }
        if (pageDailyLimit > 0 && currentCount >= pageDailyLimit) {
            return new State(ResultCodeEnum.RECOGNIZE_PAGE_EXCEED_LIMIT);
        }

        // 增加计数
        Long afterValue = operations.increment(key, increament);
        logger.debug("用户: {}, 今天已识别页数: {}", userId, afterValue);

        // 设置过期时间
        if (existValue != null) {
            Instant expireDay = now.toLocalDate().plusDays(3).atStartOfDay(ZoneId.systemDefault()).toInstant();
            java.util.Date expireDate = Date.from(expireDay);
            operations.getOperations().expireAt(key, expireDate);
        }

        return new State(ResultCodeEnum.SUCCESS);
    }
}
